/* Sockets en mode stream; proto tcp ; Ici serveur Ce programme
   -servicecomprix- se met en attente de r'ec'eption ; il recoit
   un uid et doit r'epondre par le nom.
   Boucle en faisant une d'el'egation (fork) pour chaque client.
*/
using namespace std;
#include <stdio.h>//perror
#include <sys/types.h>
//#include <iostream> ces quatre sont dans sock.h
//#include <netinet/in.h>
//#include <netdb.h>
//#include <arpa/inet.h>
#include <sys/socket.h>//constantes
#include <fstream>
#include <unistd.h>//close
#include <pwd.h>
#include "sock.h"
#include "sockdist.h"



main(){
  /* etape A : une BR publique */
  Sock brPub(SOCK_STREAM, (short)21345,0);
  int descBrPub;
  if (brPub.good()) descBrPub=brPub.getsDesc();//on recupere le descripteur
  else {
    cout<<"pb BR publique"<<endl;
    exit(1);
  }

  /* etape B : initialiser la file d'attente */
  cout <<" avant de faire listen ; return svp pour le faire";
  cin.get();
  cout << endl;
  /* on limite a 5 la longueur de la file */
  int oreille=listen(descBrPub,5);
  if (oreille < 0){
    cout <<"je suis sourd(e)"<<endl;
    close (descBrPub);
    exit (0);
  }

  /* etape C */ /* Plus qu'a attendre les clients */
  cout << "accept n' est pas encore fait "<<endl;
  cout <<"on attend que les clients demandent une connexion; " <<endl;
  cout  << "return svp lorsque tout est pret";
  cin.get () ;
  cout << endl ;
  
  while (true){
    /* pour la BR dialogue (le cv) */
    struct sockaddr_in brCv ;

    /* etape D */ /* des que quelqu'un a demande une connexion on l'accepte */
    socklen_t lgbrCv = sizeof (struct sockaddr_in);
    int descBrCv = accept (descBrPub, (struct sockaddr *)&brCv, &lgbrCv);
    if (descBrCv < 0){
      perror ( "servicecomprix:");
      cout <<"de servicecomprix: accept refuse"<<endl;
      exit (0);
    }
    else{
      cout << "du serveur servicecomprix : connexion acceptee" << endl;
    }

   switch( pid_t tispoun=fork()){
     case -1 :
     {
       cout <<"erreur fork"<<endl;
       exit(0);
       break;
     }
     case 0 :
     {
       close (descBrPub);
       /* On consulte notre boite a lettres */
       uid_t uidVoulu;
       int rcv = recv (descBrCv, &uidVoulu, sizeof uidVoulu, 0) ;
       if (rcv < 0) {
         perror("de servicecomprix, apres recv:");
         close (descBrCv);
         exit (0);
       }

       /* on cherche le nom de cet utilisateur ; il faudrait tester
          si le retour de getpwuid n'est pas NULL*/
       struct passwd *identVoulu=getpwuid(uidVoulu);
       int lgident=strlen(identVoulu->pw_name);

       char bonj[]="Tiens, bonjour ";
       int lgbonj=strlen(bonj);
       char buffer[256] ; /* prevu pour le message recu */
       memcpy(buffer, bonj, lgbonj);
       memcpy (&buffer[strlen(bonj)], identVoulu->pw_name, lgident);
       int snd = send (descBrCv ,buffer , lgbonj+lgident, 0 ) ;
       if (snd < 0) {
         perror("de servicecomprix, apres send:");
         close (descBrCv);
         exit (0);
       }
       //cout <<"on a envoy'e "<<lgbonj+lgident<<"caracteres"<<endl;
       close (descBrCv);
       exit(0);
     }
   default : {close (descBrCv); break;}
   }
  }
  //jamais atteint car en dehors du while (true).
  close (descBrPub);
}

